#include "SimulatedCastlingAction.hpp"

CastlingAction::CastlingFunction* SimulatedCastlingAction::undo_cast_funcs[] = 
{	
	&SimulatedCastlingAction::undo_castling_queen_side,
	&SimulatedCastlingAction::undo_castling_king_side
};

void SimulatedCastlingAction::undo_castling_queen_side(Chess::Color color)
{
	try
	{
		Chessboard* 	cboard = Chess::getInstance()->getChessboard();
		unsigned int	king_x = (color == Chess::WHITE) ? KING_WHITE_INIT_X : KING_BLACK_INIT_X;
		unsigned int	king_nx = (color == Chess::WHITE) ? (KING_WHITE_INIT_X - 2) : (KING_BLACK_INIT_X + 2);
		unsigned int	rook_nx = (color == Chess::WHITE) ? (king_nx + 1) : (king_nx - 1);
		unsigned int	rook_x = (color == Chess::WHITE) ? ROOK_INIT_0_X : ROOK_INIT_1_X;
		
		Piece*	rook = cboard->getCell(Position(rook_nx, 0, color))->getPiece();
		Piece*	king = cboard->getCell(Position(king_nx, 0, color))->getPiece();
		
		rook->getCell()->setPiece(0);
		king->getCell()->setPiece(0);
		
		cboard->getCell(Position(rook_x, 0, color))->setPiece(rook);
		cboard->getCell(Position(king_x, 0, color))->setPiece(king);
		
		
		rook->setCell(cboard->getCell(Position(rook_x, 0, color)));
		king->setCell(cboard->getCell(Position(king_x, 0, color)));
		
		rook->setNbMovements(rook->getNbMovements() - 1);
		king->setNbMovements(king->getNbMovements() - 1);
		
	}
	catch (Exception*	e)
	{	throw e;	}
}

void SimulatedCastlingAction::undo_castling_king_side(Chess::Color color)
{
	try
	{
		Chessboard* 	cboard = Chess::getInstance()->getChessboard();
		unsigned int	king_x = (color == Chess::WHITE) ? KING_WHITE_INIT_X : KING_BLACK_INIT_X;
		unsigned int	king_nx = (color == Chess::WHITE) ? (KING_WHITE_INIT_X + 2) : (KING_BLACK_INIT_X - 2);
		unsigned int	rook_nx = (color == Chess::WHITE) ? (king_nx - 1) : (king_nx + 1);
		unsigned int	rook_x = (color == Chess::WHITE) ? ROOK_INIT_1_X : ROOK_INIT_0_X;
		
		Piece*	rook = cboard->getCell(Position(rook_nx, 0, color))->getPiece();
		Piece*	king = cboard->getCell(Position(king_nx, 0, color))->getPiece();
		
		rook->getCell()->setPiece(0);
		king->getCell()->setPiece(0);
		
		cboard->getCell(Position(rook_x, 0, color))->setPiece(rook);
		cboard->getCell(Position(king_x, 0, color))->setPiece(king);
		
		
		rook->setCell(cboard->getCell(Position(rook_x, 0, color)));
		king->setCell(cboard->getCell(Position(king_x, 0, color)));
		
		rook->setNbMovements(rook->getNbMovements() - 1);
		king->setNbMovements(rook->getNbMovements() - 1);
	}
	catch (Exception*	e)
	{	throw e;	}
	
}


SimulatedCastlingAction::SimulatedCastlingAction(Chess::Color color, CastlingAction::Type ctype)
	:	CastlingAction(color, ctype), SimulatedAction()
{}

SimulatedCastlingAction::~SimulatedCastlingAction()
{}

void SimulatedCastlingAction::undo()
{
	try
	{	
		CastlingAction::CastlingFunction* func = 0;
		
		func = *SimulatedCastlingAction::undo_cast_funcs[this->ctype];
		func(this->color);
	}
	catch (Exception* e)
	{	throw e;	}
}

void SimulatedCastlingAction::reset(CastlingAction::Type type)
{	ctype = type;	}
